package com.example.gateway.filter;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import util.JwtUtil;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * 网关做token校验 身份校验交给后面的业务服务器 因为不同的业务服务器 权限设置的规则不一样
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);

    //请求白名单  可以配置在yml中
    private String[] whiteUrlList = new String[]{"/user/loginWithUsernameAndPass","/role/addOffice", "reg"};


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求路径
        String url = exchange.getRequest().getURI().getPath();
        log.info("请求路径：{}", url);
        //请求白名单路径 跳过验证
        if(Arrays.asList(whiteUrlList).contains(url)){
            return chain.filter(exchange);
        }
        //取出token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        //token非空校验
        if (token == null || token.isEmpty()) {
            return errorRsp("token不能为空", exchange);
        }
        //token合法性和过期校验
        try {
            JwtUtil.verifyToken(token);
        } catch (Exception e) {
            e.printStackTrace();
            return errorRsp("token无效：不合法或过期", exchange);
        }
        //token载荷信息校验
        String userId = JwtUtil.parseToken(token).get("userId").asString();
        String roleId = JwtUtil.parseToken(token).get("roleId").asString();
        String roleSign = JwtUtil.parseToken(token).get("roleSign").asString();

        if (userId == null || userId.isEmpty()) {
            return errorRsp("token无效：token中用户id信息不存在", exchange);
        }
        //将用户的id信息存放到请求头中 后面的服务就不需要在解析token了
        ServerHttpRequest newRequest = exchange.getRequest().mutate().header("userId", userId)
                .header("roleId",roleId).header("roleSign", roleSign)
                .build();

        ServerWebExchange serverWebExchange = exchange.mutate().request(newRequest).build();

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100;
    }


    /**
     * 生成错误响应信息
     */
    public Mono<Void> errorRsp(String msg, ServerWebExchange exchange) {
        ServerHttpResponse rsp = exchange.getResponse();
        rsp.setStatusCode(HttpStatus.OK);
        rsp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        byte[] responseByte = ("{\"code\":50008,\"msg\":\"" + msg +
                "\",\"content\":null}")
                .getBytes(StandardCharsets.UTF_8);

        DataBuffer buffer = rsp.bufferFactory().wrap(responseByte);

        return rsp.writeWith(Flux.just(buffer));
    }


}
